package com.whc.user.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
import com.whc.api.dto.PayApplyDTO;
import com.whc.common.constant.JwtClaimsConstant;
import com.whc.common.constant.RedisHeader;
import com.whc.common.context.BaseContext;
import com.whc.common.domain.Result;
import com.whc.common.utils.JwtUtil;
import com.whc.user.config.JwtProperties;
import com.whc.user.domain.dto.RechargeDto;
import com.whc.user.domain.dto.UserLoginDto;
import com.whc.user.domain.dto.UserRegisterDto;
import com.whc.user.domain.entity.RechargeMessage;
import com.whc.user.domain.entity.User;
import com.whc.api.dto.UserPageVo;
import com.whc.user.domain.vo.UserVo;
import com.whc.user.service.UserService;
import com.whc.user.util.BloomFilterUtil;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("/client/user")
@Api(tags = "用户模块")
@Slf4j

public class UserController {



    @Autowired
    private UserService userService;
    @Resource
    private JwtProperties jwtProperties;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;



    @ApiOperation("付钱")
    @PutMapping("/payMoney")
    public Result payMoney(@RequestBody PayApplyDTO payApplyDTO){
        userService.payMoney(payApplyDTO);
        return Result.success();
    }

    @ApiOperation("充值请求")
    @PostMapping("/recharge")
    public Result recharge(@RequestBody RechargeDto rechargeDto){
        userService.recharge(rechargeDto);
        return Result.success();
    }

    @ApiOperation("查询所有充值请求")
    @GetMapping("selectAllRecharge")
    public Result<List<RechargeMessage>> selectAllRecharge(){
        List<RechargeMessage> res=userService.selectAllRecharge();

        return Result.success(res);
    }

    @ApiOperation("管理充值请求")
    @PostMapping("updateRecharge")
    public Result updateRecharge (@RequestParam("id") Long id,@RequestParam("type") Long type){
        userService.updateRecharge(id,type);
        return Result.success();
    }



    @ApiOperation("修改用户状态")
    @GetMapping("/updateOnline")
    public Result updateUserOnline(@RequestParam("id") Long id,@RequestParam("online") Long online){
        //在线
        if(online==1){
            //之前时不在线
            if(!redisTemplate.hasKey(RedisHeader.userOnline+id)){
                redisTemplate.opsForValue().set(RedisHeader.userOnline +id, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
            }
        }else{
            //之前在线
            if(redisTemplate.hasKey(RedisHeader.userOnline+id)){
                redisTemplate.delete(RedisHeader.userOnline+id);
            }
        }
        return Result.success();
    }

    @ApiOperation("查询用户状态")
    @GetMapping("/getOnline")
    public Result<Integer> getUserOnline(@RequestParam("fid") Long fid){
        if(redisTemplate.hasKey(RedisHeader.userOnline+fid)){
            return Result.success(1);
        }
        return Result.success(0);
    }

    @ApiOperation("获取验证码")
    @GetMapping("/getCode")
    public Result<Map<String, String>> getCode(){
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 50);
        String uuid = UUID.randomUUID().toString();
        //创建一个流，并把验证码输入到上面
        FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream();
        captcha.write(outputStream);
        String textCode=captcha.getCode();
        //设置一分钟的验证码缓存(不合实际)
//        redisTemplate.opsForValue().set(uuid,textCode, Duration.ofMinutes(1));
        redisTemplate.opsForValue().set(uuid,textCode);
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(5);
        map.put("uuid",uuid);
        map.put("textCode",textCode);
        map.put("img", Base64.encode(outputStream.toByteArray()));
        return Result.success(map);
    }


    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result<UserVo> login(@RequestBody UserLoginDto userLoginDto) {
        String uuid = userLoginDto.getUuid();
        String textCodeRedis = (String)redisTemplate.opsForValue().get(uuid);

        if(!userLoginDto.getTextCode().equalsIgnoreCase(textCodeRedis)){
            redisTemplate.delete(uuid);
            return Result.error("验证码错误");
        }
//        //删除redis里的验证码
        if(redisTemplate.hasKey(uuid)){
            redisTemplate.delete(uuid);
        }

        //拿到user,封装给vo对象，并且创建jwt，给到vo对象
        User user = userService.Login(userLoginDto);
        UserVo userVo=new UserVo();
        BeanUtils.copyProperties(user,userVo);
        //生成jwt
        HashMap<String,Object> map = new HashMap<>();
        map.put(JwtClaimsConstant.USER_ID,user.getId());
        String jwt = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), map);
        userVo.setToken(jwt);
//        log.info("id:"+user.getId()+"姓名"+userVo.getUsername()+"token:"+userVo.getToken());
//        log.info("校验令牌");
//        Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), jwt);
//        long userId = (int)claims.get(JwtClaimsConstant.USER_ID);
//        log.info("解析中获取到当前用户的id:{}",userId);
        redisTemplate.opsForValue().set(RedisHeader.userId+user.getId(),1,5, TimeUnit.MINUTES);

        return Result.success(userVo);

    }


    @ApiOperation("退出登录")
    @PostMapping("/logout")
    public Result<String> logout(){
        //只需把reids中的jwt信息消除即可
        System.out.println("退出登录");
        Long userId= BaseContext.getCurrentId();
        redisTemplate.delete(RedisHeader.userId+userId);
        return Result.success("退出成功");
    }

    @ApiOperation("注册接口")
    @PostMapping("/register")
    public Result register(@RequestBody UserRegisterDto userRegisterDto){
        String uuid = userRegisterDto.getUuid();

        String textCodeRedis = (String)redisTemplate.opsForValue().get(uuid);
        if(!userRegisterDto.getTextCode().equalsIgnoreCase(textCodeRedis)){
            redisTemplate.delete(uuid);
            return Result.error("验证码错误");
        }
        //删除redis里的验证码
        if(redisTemplate.hasKey(uuid)){
            redisTemplate.delete(uuid);
        }

        userService.Register(userRegisterDto);
        return Result.success();
    }

    @ApiOperation("根据id查询用户")
    @GetMapping("/getUserById")
    public Result<UserPageVo> getUserById(@RequestParam("userId") Integer userId){
        long index = BloomFilterUtil.getIndex(userId);
        Boolean flag = redisTemplate.opsForValue().getBit(BloomFilterUtil.whiteUserHead, index);
        if(!flag){
            return Result.error("不存在该用户");
        }
        UserPageVo userPageVo=userService.getUserById(userId);
        return Result.success(userPageVo);
    }

    @ApiOperation("根据多个id查询用户")
    @GetMapping("/getUserByIds")
    public Result<List<UserPageVo>> getUserByIds(@RequestParam("userIds") List<Long> userIds){
        if(userIds==null||userIds.size()==0){
            return Result.success();
        }
        List<UserPageVo> userPageVo=userService.getUserByIds(userIds);
        return Result.success(userPageVo);
    }


    @ApiOperation("根据名称查询用户")
    @GetMapping("/getUserByName")
    public Result<User> getUserByName(@RequestParam("userName") String userName){
        User user=userService.getUserByName(userName);
        System.out.println(user);
        return Result.success(user);
    }

    @ApiOperation("返回用户id接口")
    @GetMapping("/getUserId")
    public Result<Long> getUsername(HttpSession session){
        long username =(long)session.getAttribute("userId");
        return Result.success(username);
    }


}
